package com.bird.web.controller.system.ts;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.bird.common.annotation.Log;
import com.bird.common.constant.Constants;
import com.bird.common.enums.BusinessType;
import com.bird.common.utils.Assert;
import com.bird.common.utils.StringUtil;
import com.bird.common.utils.tkmybatis.TK;
import com.bird.common.utils.tkmybatis.TKCriteria;
import com.bird.framework.domain.Result;
import com.bird.framework.domain.page.PageDomain;
import com.bird.framework.utils.SecurityUtils;
import com.bird.system.domain.bo.LoginUser;
import com.bird.system.domain.entity.TsReqLogEntity;
import com.bird.system.domain.params.TsReqLogQueryParam;
import com.bird.system.domain.params.TsReqLogUpdateParam;
import com.bird.system.domain.vo.TsReqLogListPcVO;
import com.bird.system.enums.BaseEnum;
import com.bird.system.enums.FlagEnum;
import com.bird.system.service.ISysConfigService;
import com.bird.system.service.ITsReqLogService;
import com.bird.web.controller.common.BaseController;
import com.github.pagehelper.PageInfo;
import com.github.stupdit1t.excel.Column;
import com.github.stupdit1t.excel.ExcelUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 请求日志Controller
 *
 * @author bird
 * @date 2020-09-23
 */
@Api(tags = "请求日志")
@RestController
@RequestMapping("/system/reqLog")
public class TsReqLogController extends BaseController {

	@Autowired
	private ITsReqLogService tsReqLogService;

	@Autowired
	private ISysConfigService sysConfigService;

	@ApiOperation("查询请求日志列表")
	@PreAuthorize("@ss.hasPermi('system:log:list')")
	@GetMapping("/list")
	public Result<PageInfo<TsReqLogListPcVO>> list(TsReqLogQueryParam queryParams) {
		startPage();
		queryParams.setUserId(SecurityUtils.getLoginUser().getUserId());
		List<TsReqLogListPcVO> list = tsReqLogService.selectListPC(queryParams);
		return page(list);
	}

	@ApiOperation("获取请求日志详细信息")
	@PreAuthorize("@ss.hasPermi('system:log:query')")
	@GetMapping(value = "/{id}")
	public Result<TsReqLogEntity> info(@PathVariable("id") Long id) {
		return ok(tsReqLogService.selectById(id));
	}

	@ApiOperation("新增请求日志")
	@PreAuthorize("@ss.hasPermi('system:log:add')")
	@Log(title = "请求日志", businessType = BusinessType.INSERT)
	@PostMapping
	public Result<Long> add(@RequestBody TsReqLogUpdateParam updateParam) {
		return ok(tsReqLogService.insertPC(updateParam));
	}

	@ApiOperation("修改请求日志")
	@PreAuthorize("@ss.hasPermi('system:log:edit')")
	@Log(title = "请求日志", businessType = BusinessType.UPDATE)
	@PutMapping
	public Result<Integer> edit(@RequestBody TsReqLogUpdateParam updateParam) {
		return ok(tsReqLogService.updateByIdPC(updateParam));
	}

	@ApiOperation("删除请求日志")
	@PreAuthorize("@ss.hasPermi('system:log:remove')")
	@Log(title = "请求日志", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
	public Result<Integer> remove(@PathVariable Long[] ids) {
		return ok(tsReqLogService.deleteByIds(ids));
	}

	@ApiOperation("清除请求日志")
	@Log(title = "请求日志", businessType = BusinessType.DELETE)
	@DeleteMapping("/clean/{pwd}")
	public Result<Integer> clean(@PathVariable String pwd) {
		LoginUser loginUser = SecurityUtils.getLoginUser();
		String password = loginUser.getPassword();
		Assert.isFalse(SecurityUtils.matchesPassword(pwd, password), "清除失败, 密码错误!");
		return ok(tsReqLogService.deleteByParams(TsReqLogEntity.builder().creSb(SecurityUtils.getLoginUser().getUserId()).build()));
	}

	@ApiOperation("日志导出")
	@Log(title = "日志导出", businessType = BusinessType.EXPORT)
	@GetMapping("/export")
	public void export(TsReqLogQueryParam queryParams) throws Exception {
		TKCriteria<TsReqLogEntity, Object> query = TK.select(TsReqLogEntity.class).where().andEqualTo(TsReqLogEntity::getCreSb, queryParams.getUserId());
		if (queryParams.getConfigId() != null) {
			query.andEqualTo(TsReqLogEntity::getConfigId, queryParams.getConfigId());
		}
		if (StringUtil.isNotBlank(queryParams.getGroupData())) {
			query.andEqualTo(TsReqLogEntity::getGroupData, queryParams.getGroupData());
		}
		if (StringUtil.isNotBlank(queryParams.getRspResult())) {
			query.andEqualTo(TsReqLogEntity::getRspResult, queryParams.getRspResult());
		}
		if (StringUtil.isNotBlank(queryParams.getMatchPattern())) {
			query.andEqualTo(TsReqLogEntity::getMatchPattern, queryParams.getMatchPattern());
		}
		if (StringUtil.isNotBlank(queryParams.getLastReqId())) {
			query.andLike(TsReqLogEntity::getLastReqId, queryParams.getLastReqId() + "%");
		}
		int totalSize = tsReqLogService.countByParams(query.end());
		Integer pageSize = Integer.valueOf(sysConfigService.selectConfigByKey(Constants.SysConfig.EXPORT_PAGE_SIZE));
		int pageNum = 1;
		int pageTotal = (totalSize - 1) / pageSize + 1;
		try (Workbook workbook = ExcelUtils.createBigWorkbook()) {
			while (pageNum <= pageTotal) {
				PageDomain.startPage(pageNum, pageSize);
				List<TsReqLogEntity> list = tsReqLogService.selectList(query.end());
				for (TsReqLogEntity tsReqLogEntity : list) {
					try {
						tsReqLogEntity.setStoreValObject(JSONObject.parseObject(tsReqLogEntity.getStoreVal(), Feature.OrderedField));
					} catch (Exception e) {

					}
					BaseEnum baseEnum = BaseEnum.valueOfEnum(FlagEnum.class, tsReqLogEntity.getMatchPattern());
					tsReqLogEntity.setMatchPattern(baseEnum.getValue());

				}
				List<String> headerList = Stream.of("配置名称", "数据组", "号码", "请求Url", "匹配").collect(Collectors.toList());
				List<Column> columnList = Stream.of(
						Column.field("configName").width(5),
						Column.field("groupName").width(5),
						Column.field("groupData").width(10),
						Column.field("theUrl").width(20),
						Column.field("matchPattern").width(2)
				).collect(Collectors.toList());

				//扩展
				int jsonLength = 0;
				JSONObject maxJson = new JSONObject(true);
				if (!list.isEmpty()) {
					for (TsReqLogEntity tsReqLogEntity : list) {
						String storeVal = tsReqLogEntity.getStoreVal();
						if (StringUtil.isNotBlank(storeVal)) {
							try {
								JSONObject json = JSONObject.parseObject(storeVal, Feature.OrderedField);
								Set<String> keys = json.keySet();
								if (keys.size() > jsonLength) {
									jsonLength = keys.size();
									maxJson = json;
								}
							} catch (Exception e) {

							}
						}
					}
				}
				if (jsonLength > 0) {
					Set<String> keys = maxJson.keySet();
					for (String key : keys) {
						headerList.add(key);
						columnList.add(Column.field("storeValObject." + key).width(5));
					}
				}
				ExcelUtils.ExportRules exportRules = ExcelUtils.ExportRules.simpleRule(columnList.toArray(new Column[columnList.size()]), headerList.toArray(new String[headerList.size()]));
				exportRules.sheetName("请求日志" + pageNum);
				ExcelUtils.fillBook(workbook, list, exportRules);
				list = null;
				pageNum++;
			}
			export(workbook, "请求日志" + DateUtil.date().toString(Constants.DatePattern.NORM_DATE_PATTERN) + ".xlsx");
		}


	}
}
